package top.xia17.plugins.fast.auth.login;

import top.xia17.plugins.fast.common.autoconfiguration.TokenProperties;
import top.xia17.plugins.fast.common.database.redis.RedisUtils;
import top.xia17.plugins.fast.common.exceptions.BadRequestException;
import top.xia17.plugins.fast.common.security.token.provider.TokenProvider;
import top.xia17.plugins.fast.common.utils.VerifyUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import top.xia17.plugins.fast.auth.autoconfiguraion.AuthProperties;
import top.xia17.plugins.fast.auth.model.req.LoginReq;
import top.xia17.plugins.fast.auth.model.resp.LoginResp;
import top.xia17.plugins.fast.user.model.dto.UserDto;
import top.xia17.plugins.fast.user.service.UserService;
import java.util.Arrays;
import java.util.Set;

/**
 * 抽象的登录辅助类
 * @author xia17
 * @since 2022/6/1 11:44
 */
@RequiredArgsConstructor
public abstract class AbstractLoginHelper<T extends LoginReq> implements LoginHelper<T> {

    private final AuthProperties authProperties;
    private final RedisUtils redisUtils;
    private final UserService userService;
    private final TokenProvider tokenProvider;
    private final TokenProperties tokenProperties;


    /**
     * 获取登录方式名字
     * @return /
     */
    public abstract String getLoginMethodName();

    /**
     * 获取不支持时的异常提示信息
     * @return /
     */
    public abstract String getNotSupportErrorMessage();

    /**
     * 验证用户是否存在
     * @param req 登录请求参数
     * @return /
     */
    public abstract UserDto verifyUser(T req);


    /**
     * 验证是否支持本登录方式
     */
    public void verifySupport(){
        // 是否支持用户名密码登录
        if (!Arrays.asList(authProperties.getLoginSupportMethods()).contains(getLoginMethodName())){
            throw new BadRequestException(getNotSupportErrorMessage());
        }
    }

    /**
     * 验证图形验证码
     * @param uuid uuid
     * @param value 值
     */
    public void verifyImgCaptcha(String uuid , String value){
        // 是否开启图片验证码
        if (authProperties.getLoginCaptchaEnabled()) {
            VerifyUtil.notBlank(uuid, "验证码不能为空，captchaUuid is blank !");
            VerifyUtil.notBlank(value, "验证码不能为空 !");
            Object val = redisUtils.get(uuid);
            if (val == null || "".equals(val.toString())) {
                throw new BadRequestException("验证码已过期！");
            }
            // 清除验证码
            redisUtils.del(uuid);
            if (!val.toString().equals(value)) {
                throw new BadRequestException("验证码错误！");
            }
        }
    }


    @Override
    public LoginResp login(T req, HttpServletResponse response) {
        // 验证是否支持(启用)
        this.verifySupport();
        // 验证图形验证码
        this.verifyImgCaptcha(req.getCaptchaUuid(),req.getCaptchaValue());
        // 验证用户
        UserDto user = this.verifyUser(req);
        // 构建返回结果
        return this.buildLoginSuccessResp(user,response);
    }

    /**
     * 构建登录成功后返回结果
     *
     * @param user 用户信息
     * @param response httpResponse
     * @return LoginResp
     */
    public LoginResp buildLoginSuccessResp(UserDto user , HttpServletResponse response){
        // 获取权限信息
        Set<String> permissions = userService.getUserPermissions(user.getId());
        user.setPermissions(permissions);
        String token = tokenProvider.generateTokenAndSave(user);
        token = tokenProperties.getTokenPrefix() + " " + token;
        // 在返回头里面添加token ， 注意，token前缀和token之间用一个空格间隔
        response.setHeader(tokenProperties.getTokenHeaderKey(), token);
        return new LoginResp(token, user);
    }



}
